﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Xml.Linq;
using System.Xml.XPath;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Communication.Base;
using UtilZ.Dotnet.Ex.Communication.Net.Web;
using UtilZ.Dotnet.Ex.Json;
using UtilZ.Dotnet.Ex.Log;
using UtilZ.Dotnet.Ex.Model;
using UtilZ.Tool.HostPluginBase;

namespace UtilZ.Tool.WatchdogPlugin
{
    /// <summary>
    /// 主机看门狗插件类-api函数
    /// </summary>
    [Route("api/v1/watchdog")]
    public partial class Watchdog
    {
        //http://127.0.0.1:5200/api/v1/watchdog/test
        [HttpGet("test")]
        public ApiResult TestApi()
        {
            try
            {
                //AppItem appItem = new AppItem()
                //{
                //    AppExeFilePath = @"D:\Soft\Color\Color.exe",
                //    AppName = "ColorApp",
                //    Arguments = "",
                //    CPURate = 23,
                //    DelayStartTime = 23,
                //    Des = "AAAAABBBBB0001",
                //    IsMonitor = true,
                //    MemUse = 5600,
                //    RunStatus = true,
                //    StartTime = DateTime.Parse("2023-03-10 09:10:12"),
                //    SoftwVer = "1.2.3",
                //    TcpPortUse = "35;69",
                //    ThrNum = 5,
                //    UdpPortUse = "12;23"
                //};
                //this._appItemDic.Add(appItem.AppName, appItem);
                //this.PushAppStatusChangedNotify(appItem);
                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }


        /// <summary>
        /// 添加应用到监视
        /// </summary>
        /// <param name="appItem"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/addApp
        [HttpPost("addApp")]
        public ApiResult AddAppApi([FromBody] AppItem appItem)
        {
            try
            {
                ApiResult checkReult = this.CheckAddAppItem(appItem);
                if (checkReult != null)
                {
                    return checkReult;
                }

                appItem.Init();
                this._appItemDic.Add(appItem.AppName, appItem);
                appItem.StartCheck(this._firstAppStartTimestamp);
                this.SaveData();
                this.CheckMonitorThread();

                WatchdogLRPCHelper.PushAppChangedNotify(new AppChangedMessage(AppChangedMessage.APP_ADD, appItem.AppName)
                {
                    RunStatus = false
                });

                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }

        /// <summary>
        /// 添加应用到监视
        /// </summary>
        /// <param name="appItem"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/addApps
        [HttpPost("addApps")]
        public ApiResult AddAppApi([FromBody] List<AppItem> appItemList)
        {
            try
            {
                if (appItemList == null || appItemList.Count == 0)
                {
                    return new ApiResult(ApiResultStatus.Fail, "没有可操作的应用项.");
                }

                ApiResult checkReult;
                foreach (var appItem in appItemList)
                {
                    checkReult = this.CheckAddAppItem(appItem);
                    if (checkReult != null)
                    {
                        return checkReult;
                    }
                }

                foreach (var appItem in appItemList)
                {
                    appItem.Init();
                    this._appItemDic.Add(appItem.AppName, appItem);
                    appItem.StartCheck(this._firstAppStartTimestamp);
                }
                this.SaveData();
                this.CheckMonitorThread();

                WatchdogLRPCHelper.PushAppChangedNotify(new AppChangedMessage(AppChangedMessage.APP_ADD)
                {
                    AppNames = appItemList.Select(t => { return t.AppName; }).ToList(),
                    RunStatus = false
                });

                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }

        private ApiResult CheckAddAppItem(AppItem appItem)
        {
            if (appItem == null)
            {
                return new ApiResult(ApiResultStatus.Fail, "应用项不能为空.");
            }

            if (string.IsNullOrWhiteSpace(appItem.AppName))
            {
                return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或null或全空格.");
            }

            if (this._appItemDic.ContainsKey(appItem.AppName))
            {
                return new ApiResult(ApiResultStatus.Fail, $"应用名称\"{appItem.AppName}\"重复.");
            }

            if (string.IsNullOrWhiteSpace(appItem.AppExeFilePath))
            {
                return new ApiResult(ApiResultStatus.Fail, "文件路径不能为空或null或全空格.");
            }

            if (string.IsNullOrWhiteSpace(Path.GetPathRoot(appItem.AppExeFilePath)))
            {
                string appExeFilePath = EnvironmentEx.GetFilePathFromEnvPath(appItem.AppExeFilePath);
                if (!File.Exists(appExeFilePath))
                {
                    return new ApiResult(ApiResultStatus.Fail, $"应用程序文件\"{appItem.AppExeFilePath}\"不存在.");
                }
            }
            else
            {
                if (!File.Exists(appItem.AppExeFilePath))
                {
                    return new ApiResult(ApiResultStatus.Fail, $"应用程序文件\"{appItem.AppExeFilePath}\"不存在.");
                }
            }

            return null;
        }

        private ApiResult CheckModifyAppItem(AppItem appItem)
        {
            if (appItem == null)
            {
                return new ApiResult(ApiResultStatus.Fail, "应用项不能为空.");
            }

            if (string.IsNullOrWhiteSpace(appItem.AppName))
            {
                return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或null或全空格.");
            }

            if (string.IsNullOrWhiteSpace(appItem.OldAppName))
            {
                return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或null或全空格.");
            }

            if (!this._appItemDic.ContainsKey(appItem.OldAppName))
            {
                return new ApiResult(ApiResultStatus.Fail, $"要修改的应用\"{appItem.OldAppName}\"不存在.");
            }

            return null;
        }


        /// <summary>
        /// 修改应用
        /// </summary>
        /// <param name="appItem"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/modifyApp
        [HttpPost("modifyApp")]
        public ApiResult ModifyAppApi([FromBody] AppItem appItem)
        {
            try
            {
                ApiResult checkReult = this.CheckModifyAppItem(appItem);
                if (checkReult != null)
                {
                    return checkReult;
                }

                //更新使用替换方法,将原有的对象直接给释放了,使用新的对象,理想加简单
                if (this._appItemDic.TryGetValue(appItem.OldAppName, out var oldAppItem))
                {
                    oldAppItem.Update(appItem);
                }
                else
                {
                    appItem.Init();
                    this._appItemDic.Add(appItem.AppName, appItem);
                    appItem.StartCheck(this._firstAppStartTimestamp);
                }

                this.SaveData();

                WatchdogLRPCHelper.PushAppChangedNotify(new AppChangedMessage(AppChangedMessage.APP_MODIFY, appItem.AppName)
                {
                    RunStatus = false
                });


                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }

        /// <summary>
        /// 添加应用到监视
        /// </summary>
        /// <param name="appItem"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/addApps
        [HttpPost("modifyApps")]
        public ApiResult ModifyAppApi([FromBody] List<AppItem> appItemList)
        {
            try
            {
                if (appItemList == null || appItemList.Count == 0)
                {
                    return new ApiResult(ApiResultStatus.Fail, "没有可操作的应用项.");
                }

                ApiResult checkReult;
                foreach (var appItem in appItemList)
                {
                    checkReult = this.CheckModifyAppItem(appItem);
                    if (checkReult != null)
                    {
                        return checkReult;
                    }
                }

                foreach (var appItem in appItemList)
                {
                    //更新使用替换方法,将原有的对象直接给释放了,使用新的对象,理想加简单
                    if (this._appItemDic.TryGetValue(appItem.OldAppName, out var oldAppItem))
                    {
                        oldAppItem.Update(appItem);
                    }
                    else
                    {
                        appItem.Init();
                        this._appItemDic.Add(appItem.AppName, appItem);
                        appItem.StartCheck(this._firstAppStartTimestamp);
                    }
                }
                this.SaveData();

                WatchdogLRPCHelper.PushAppChangedNotify(new AppChangedMessage(AppChangedMessage.APP_MODIFY)
                {
                    AppNames = appItemList.Select(t => { return t.AppName; }).ToList(),
                    RunStatus = false
                });

                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }




        /// <summary>
        /// 从监视列表中移除应用
        /// </summary>
        /// <param name="appNameList"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/removeApps
        [HttpPost("removeApps")]
        public ApiResult RemoveAppApi([FromBody] List<string> appNameList)
        {
            try
            {
                if (appNameList == null || appNameList.Count == 0)
                {
                    return new ApiResult(ApiResultStatus.Fail, "没有可操作的应用项.");
                }

                foreach (var appName in appNameList)
                {
                    if (string.IsNullOrWhiteSpace(appName))
                    {
                        return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或null或全空格.");
                    }

                    if (this._appItemDic.TryRemove(appName, out var oldAppItem))
                    {
                        oldAppItem.DisableMonitor();
                        oldAppItem.Dispose();
                    }
                }

                this.SaveData();
                this.CheckMonitorThread();

                WatchdogLRPCHelper.PushAppChangedNotify(new AppChangedMessage(AppChangedMessage.APP_REMOVE)
                {
                    AppNames = appNameList,
                    RunStatus = false
                });

                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }

        /// <summary>
        /// 从监视列表中移除应用
        /// </summary>
        /// <param name="appNameList"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/removeApp
        [HttpGet("removeApp?appName={appName}")]
        public ApiResult RemoveAppApi(string appName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(appName))
                {
                    return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或全空格或null");
                }

                if (string.IsNullOrWhiteSpace(appName))
                {
                    return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或null或全空格.");
                }

                if (this._appItemDic.TryRemove(appName, out var oldAppItem))
                {
                    oldAppItem.DisableMonitor();
                    oldAppItem.Dispose();
                }

                this.SaveData();
                this.CheckMonitorThread();

                WatchdogLRPCHelper.PushAppChangedNotify(new AppChangedMessage(AppChangedMessage.APP_REMOVE, appName)
                {
                    RunStatus = false
                });

                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }




        /// <summary>
        /// 关闭应用
        /// </summary>
        /// <param name="appName"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/closeApp?appName=应用名称
        [HttpGet("closeApp?appName={appName}")]
        public ApiResult CloseAppApi(string appName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(appName))
                {
                    return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或全空格或null");
                }

                if (this._appItemDic.TryGetValue(appName, out var appItem))
                {
                    appItem.Stop();
                    this.SaveData();
                }

                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }

        /// <summary>
        /// 启动应用
        /// </summary>
        /// <param name="appName"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/startApp?appName=应用名称
        [HttpGet("startApp?appName={appName}")]
        public ApiResult StartAppApi(string appName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(appName))
                {
                    return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或全空格或null");
                }

                if (this._appItemDic.TryGetValue(appName, out var appItem))
                {
                    appItem.Start(this._firstAppStartTimestamp);
                    this.SaveData();
                }

                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }

        /// <summary>
        /// 监视应用
        /// </summary>
        /// <param name="appName"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/enableMonitorApp?appName=应用名称
        [HttpGet("enableMonitorApp?appName={appName}")]
        public ApiResult EnableAppMonitorApi(string appName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(appName))
                {
                    return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或全空格或null");
                }

                if (this._appItemDic.TryGetValue(appName, out var appItem))
                {
                    appItem.EnableMonitor();
                    this.SaveData();
                    return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
                }
                else
                {
                    return new ApiResult(ApiResultStatus.Fail, $"应用\"{appItem}\"不存在:{TimeEx.GetTimestamp()}");
                }
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }

        /// <summary>
        /// 不监视应用
        /// </summary>
        /// <param name="appName"></param>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/disableMonitorApp?appName=应用名称
        [HttpGet("disableMonitorApp?appName={appName}")]
        public ApiResult DisableAppMonitorApi(string appName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(appName))
                {
                    return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或全空格或null");
                }

                if (this._appItemDic.TryGetValue(appName, out var appItem))
                {
                    appItem.DisableMonitor();
                    this.SaveData();
                    return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
                }
                else
                {
                    return new ApiResult(ApiResultStatus.Fail, $"应用\"{appItem}\"不存在:{TimeEx.GetTimestamp()}");
                }
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }


        /// <summary>
        /// 获取指定应用名称的应用信息
        /// </summary>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/getApp?appName=应用名称
        [HttpGet("getApp?appName={appName}")]
        public ApiResult GetAppApi(string appName)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(appName))
                {
                    return new ApiResult(ApiResultStatus.Fail, "应用名称不能为空或全空格或null");
                }

                if (this._appItemDic.TryGetValue(appName, out AppItem appItem))
                {
                    return new ApiResult(ApiResultStatus.Succes, JsonSerializer.SerializeObject(appItem));
                }
                else
                {
                    return new ApiResult(ApiResultStatus.Fail, $"名称为\"{appName}\"的应用不存在.");
                }
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }

        private AppItem[] _emptyArr = new AppItem[0];
        /// <summary>
        /// 获取应用信息列表
        /// </summary>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/getAppList
        [HttpGet("getAppList")]
        public ApiResult GetAppListApi()
        {
            try
            {
                if (this._appItemDic.Count == 0)
                {
                    return new ApiResult(ApiResultStatus.Succes, JsonSerializer.SerializeObject(this._emptyArr));
                }

                var list = this._appItemDic.Values.ToList();
                return new ApiResult(ApiResultStatus.Succes, JsonSerializer.SerializeObject(list));
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }





        /// <summary>
        /// 关闭全部应用
        /// </summary>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/closeAll
        [HttpGet("closeAll")]
        public ApiResult CloseAllApi()
        {
            try
            {
                foreach (var appItem in this._appItemDic.Values)
                {
                    appItem.Stop();
                }
                this.SaveData();
                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }


        /// <summary>
        /// 启动全部应用
        /// </summary>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/startAll
        [HttpGet("startAll")]
        public ApiResult StartAllApi()
        {
            try
            {
                foreach (var appItem in this._appItemDic.Values)
                {
                    appItem.Start(this._firstAppStartTimestamp);
                }
                this.SaveData();
                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }

        /// <summary>
        /// 重启全部应用
        /// </summary>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/restartAll
        [HttpGet("restartAll")]
        public ApiResult RestartAllApi()
        {
            try
            {
                this._firstAppStartTimestamp = TimeEx.GetTimestamp();
                foreach (var appItem in this._appItemDic.Values)
                {
                    appItem.Reset();
                    appItem.Restart(this._firstAppStartTimestamp);
                }
                this.SaveData();
                return new ApiResult(ApiResultStatus.Succes, $"ok:{TimeEx.GetTimestamp()}");
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }


        /// <summary>
        /// 获取心跳检测端口
        /// </summary>
        /// <returns></returns>
        //http://127.0.0.1:5200/api/v1/watchdog/getHeartPort
        [HttpGet("getHeartPort")]
        public ApiResult GetHeartPortApi()
        {
            try
            {
                return new ApiResult(ApiResultStatus.Succes, WatchdogConfig.Instance.HeartPort.ToString());
            }
            catch (Exception ex)
            {
                return new ApiResult(ApiResultStatus.Exception, ex.ToString());
            }
        }




    }
}